package com.ocean.core.exception;

import com.ocean.core.exception.verify.ApplicationException;
import com.ocean.core.exception.verify.BadException;
import com.ocean.core.util.StringUtil;
import com.ocean.core.util.response.ResultSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Component;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.ExecutionException;

/**
 * 全局异常控制类
 *
 * @author zhang
 * @since 2020-6-2
 */
@ControllerAdvice
@Component
public class GlobalExceptionHandler {

    private final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 捕获全局异常并且返回信息
     *
     * @param request  request
     * @param response response
     * @param e        异常
     * @return 状态信息
     */
//    @ExceptionHandler(value = Exception.class)
//    @ResponseBody
//    public ResultSet<Object> exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
//        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//        log.error("异常类型：{}，异常信息：{}", e.getClass().getName(), e.getMessage());
//        log.error("异常请求 {} ：{}", request.getMethod(), request.getRequestURI());
//        e.printStackTrace();
//        return ResultSet.error(500, ConstantsAttribute.ERROR);
//    }

    /**
     * 获取用户信息失败
     *
     * @param response request
     * @param e        异常
     * @return 结果
     */
    @ExceptionHandler(value = BadException.class)
    @ResponseBody
    public ResultSet<Object> badException(BadException e, HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_OK);
        return ResultSet.error(403, e.getMessage());
    }

    /**
     * Valid验证未通过
     *
     * @param response request
     * @return 结果
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultSet<Object> validException(HttpServletResponse response, MethodArgumentNotValidException e) {
        log.warn("字段校验未通过");
        response.setStatus(HttpServletResponse.SC_OK);
        FieldError fieldError = e.getBindingResult().getFieldError();
        if (fieldError != null) {
            return ResultSet.error(406, fieldError.getDefaultMessage());
        }
        return ResultSet.error(406, "data format error");
    }

    /**
     * 请求体为空
     *
     * @param response response
     * @return 结果
     */
    @ResponseBody
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public ResultSet<Object> requestBodyNull(HttpServletResponse response, HttpMessageNotReadableException e) {
        log.warn("请求体为空或者格式错误", e);
        response.setStatus(HttpServletResponse.SC_OK);
        return ResultSet.error(406, "request body error");
    }

    /**
     * 默认异常
     *
     * @param response request
     * @param e        异常
     * @return 结果
     */
    @ExceptionHandler(value = ApplicationException.class)
    @ResponseBody
    public ResultSet<Object> normalException(ApplicationException e, HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_OK);
        return ResultSet.error(406, e.getMessage());
    }

    /**
     * 异步编排异常
     *
     * @param response request
     * @param e        异常
     * @return 结果
     */
    @ExceptionHandler(value = ExecutionException.class)
    @ResponseBody
    public ResultSet<Object> executionException(ExecutionException e, HttpServletResponse response) {
        log.error("异步编排异常：{}", e.getMessage());
        e.printStackTrace();
        response.setStatus(HttpServletResponse.SC_OK);
        String message = e.getCause().getMessage();
        if (StringUtil.isNotNull(message)) {
            return ResultSet.error(406, message);
        }
        return ResultSet.error();
    }

    /**
     * 请求类型错误
     *
     * @return 结果
     */
    @ResponseBody
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ResultSet<Object> notSupportedException(HttpServletResponse response) {
        log.warn("请求类型错误");
        response.setStatus(HttpServletResponse.SC_OK);
        return ResultSet.error();
    }

    /**
     * 没有权限访问资源
     * 解决被全局异常捕获
     *
     * @param e e
     */
//    @ExceptionHandler(value = AccessDeniedException.class)
//    public void accessDeniedException(AccessDeniedException e) {
//        log.warn("无权限访问");
//        throw e;
//    }
}
